package com.suning.sawp.service.impl.promotion;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.suning.sawp.cache.RedisClient;
import com.suning.sawp.constants.CacheKeyConstants;
import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.PromSysConstants;
import com.suning.sawp.constants.PromotionConstants;
import com.suning.sawp.constants.PromotionErrorConstants;
import com.suning.sawp.constants.TMConstants;
import com.suning.sawp.dto.common.QueryResult;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.esb.CouponRuleQueryRtn;
import com.suning.sawp.dto.esb.LocateMemberInfo;
import com.suning.sawp.dto.esb.QryActDetailRsp;
import com.suning.sawp.dto.esb.QryActDetailRsp.ActivityDetail;
import com.suning.sawp.dto.esb.QueryCouponRtn;
import com.suning.sawp.dto.esb.SendCouponRtn;
import com.suning.sawp.dto.precharge.CommonRtn;
import com.suning.sawp.dto.promotion.CheckRegisterRtn;
import com.suning.sawp.dto.promotion.CouponRecordStatis;
import com.suning.sawp.dto.promotion.CouponRecordStatisRtn;
import com.suning.sawp.dto.promotion.InCouponRecord;
import com.suning.sawp.dto.promotion.InnerCouponBlackList;
import com.suning.sawp.dto.promotion.InnerCouponDetail;
import com.suning.sawp.dto.promotion.InnerCouponRecordRtn;
import com.suning.sawp.dto.promotion.InnerRemain;
import com.suning.sawp.dto.promotion.QueryStaffName;
import com.suning.sawp.dto.register.LocateMemberRtn;
import com.suning.sawp.intf.clerk.ClerkService;
import com.suning.sawp.intf.dao.coupon.InnerCouponDaoService;
import com.suning.sawp.intf.dao.tm.TimeMachineDao;
import com.suning.sawp.intf.esb.MemberInfoService;
import com.suning.sawp.intf.promotion.InnerCouponService;
import com.suning.sawp.intf.promotion.PromotionCouponService;
import com.suning.sawp.intf.tm.vo.TimeMachineVo;
import com.suning.sawp.po.promotion.CouponBlackList;
import com.suning.sawp.po.promotion.InnerCouponRecord;
import com.suning.sawp.service.util.AESUtils;
import com.suning.sawp.service.util.ConfigUtil;
import com.suning.sawp.service.util.DJStringUtils;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.ExcelUtils;
import com.suning.sawp.service.util.GsonUtils;
import com.suning.sawp.service.util.SCMConfigUtil;
import com.suning.vgs.follow.remote.intf.StoreManRemoteService;
import com.suning.vgs.follow.remote.store.StoreManEbuyAccount;
import com.suning.vgs.follow.remote.store.StoreWorkerInfo;

/**
 * 
 * 内部优惠券接口实现<br>
 * 〈功能详细描述〉
 * 
 * @author Wuxiao
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service
public class InnerCouponServiceImpl implements InnerCouponService {

    private static final Logger LOGGER = LoggerFactory.getLogger(InnerCouponServiceImpl.class);

    @Resource
    PromotionCouponService promotionCouponService;

    @Autowired
    RedisClient redisClient;

    @Resource
    StoreManRemoteService storeManRemoteService;

    @Autowired
    MemberInfoService memberInfoService;

    @Resource
    InnerCouponDaoService innerCouponDaoService;

    @Resource
    ClerkService clerkService;
    
    @Autowired
    TimeMachineDao timeMachineDao;
    

    public static final String PARAM = "{param}";

    public static final String DATE_FORMAT_YYYYMM = "yyyyMM";

    private static final String END_TIME_SUFFIXES = " 23:59:59";

    @Override
    public ReturnMsg<List<InnerCouponDetail>> queryCouponList(String staffId) {
        return queryCouponListByStaffIdAndTrigerId(staffId,PromSysConstants.BONUS_INNER_PROMOTION);
    }
    
    /**
     * 
     * 根据staffId和trigerId 查询内部券列表
     *
     * @param staffId
     * @param trigerId
     * @return
     */
    public ReturnMsg<List<InnerCouponDetail>> queryCouponListByStaffIdAndTrigerId(String staffId,String trigerId) {
        ReturnMsg<List<InnerCouponDetail>> ret = new ReturnMsg<List<InnerCouponDetail>>();
        if (StringUtils.isBlank(staffId)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        // 获取工号绑定的易购账号
        String memberNo = getStaffMemberNo(staffId);
        if (StringUtils.isBlank(memberNo)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E003, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        List<InnerCouponDetail> list = new ArrayList<InnerCouponDetail>();
        // 掉促销中心查询活动列表
        QryActDetailRsp resp = promotionCouponService.queryProActivityList("", trigerId,PromotionConstants.PROMOT_COUPON_RESCOUCE_ONLINE, "");
        if (resp != null && PromotionConstants.SUCCESS.equals(resp.getRequestResult())) {
            List<ActivityDetail> activityList = resp.getActivityList();
            for (ActivityDetail act : activityList) {
                InnerCouponDetail coupon = new InnerCouponDetail();
                coupon.setActivityId(act.getActivityId());
                coupon.setSecurityKey(act.getActivitySecretKey());
                coupon.setActivityName(act.getActivityName());
                // 获取券详情
                coupon = createCouponDetail(coupon, memberNo,trigerId);
                if (coupon == null) {
                    continue;
                }
                list.add(coupon);
            }
        }
        ret.setData(list);
        return ret;
    }
    
    

    /**
     * 
     * 功能描述: 判断是否在黑名单中<br>
     * 〈功能详细描述〉
     * 
     * @param staffId
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public boolean isBlackList(String staffId) {
        String value = redisClient.hget(CacheKeyConstants.INNER_COUPON_BLACK_LIST, staffId);
        // redis有值
        if (null != value) {
            return true;
        } else {
            return false;
        }
    }

    private InnerCouponDetail createCouponDetail(InnerCouponDetail coupon, String memberNo,String trigerId) {
        String value = redisClient.hget(CacheKeyConstants.INNER_COUPON_DETAIL, coupon.getActivityId());
        InnerCouponDetail detail = null;
        if (value != null) {
            detail = GsonUtils.fromJson(value, InnerCouponDetail.class);
        } else {
            QueryCouponRtn couponRtn = promotionCouponService.queryCouponDetail(coupon.getActivityId(),
            		trigerId, memberNo, coupon.getSecurityKey(), "", null);
            if (couponRtn != null && PromotionConstants.SUCCESS.equals(couponRtn.getResult())) {
                detail = new InnerCouponDetail();
                detail.setActivityName(coupon.getActivityName());
                detail.setActivityId(AESUtils.encrypt(coupon.getActivityId(), ConfigConstants.AES_KEY));
                detail.setSecurityKey(coupon.getSecurityKey());
                detail.setCouponValue(couponRtn.getCouponAmount());
                detail.setCouponTypeTxt(couponRtn.getCouponType());
                CouponRuleQueryRtn couponRule = promotionCouponService.queryCouponRuleDetail(couponRtn.getCouponId());
                detail.setCouponRuleId(couponRtn.getCouponId());
                if (couponRule != null && PromotionConstants.SUCCESS.equals(couponRule.getRetFlag())) {
                    // 用券规则 全额抵用
                    detail.setCouponRule(couponRule.getRewardsPreferential());
                    detail.setUseGuide(couponRule.getCouponRulesShowMsg());
                    List<String> storeNameList = couponRule.getStoreNameList();
                    // 用券范围字段拼接,拼接规则按照产品提供 限..终端类型名称...,...商品类别....不可用
                    List<String> noUseList = couponRule.getNoUseList();
                    List<String> terminalList = couponRule.getTerminalList();
                    String terminalRule = "";
                    if (CollectionUtils.isNotEmpty(terminalList)) {
                        StringBuilder sb = new StringBuilder();
                        for (String s : terminalList) {
                            sb.append(s).append("、");
                        }
                        String template = ConfigUtil.getConfig(ConfigConstants.SAWP_CONFIG_PATH,
                                ConfigConstants.TERMINAL_TEMPLATE, ConfigConstants.DEFAULT_TERMINAL_TEMPLATE);
                        terminalRule = template.replace(PARAM, sb.toString().substring(0, sb.toString().length() - 1));
                    }
                    String noUseRule = "";
                    if (CollectionUtils.isNotEmpty(noUseList)) {
                        StringBuilder sb = new StringBuilder();
                        for (String s : noUseList) {
                            sb.append(s).append("、");
                        }
                        String template = ConfigUtil.getConfig(ConfigConstants.SAWP_CONFIG_PATH,
                                ConfigConstants.NO_USE_TEMPLATE, ConfigConstants.DEFAULT_NO_USE_TEMPLATE);
                        noUseRule = template.replace(PARAM, sb.toString().substring(0, sb.toString().length() - 1));
                    }
                    if (StringUtils.isNotBlank(terminalRule) && StringUtils.isNotBlank(noUseRule)) {
                        detail.setProductsTxt(terminalRule + "，" + noUseRule);
                    } else {
                        detail.setProductsTxt(terminalRule + noUseRule);
                    }
                    if (CollectionUtils.isNotEmpty(storeNameList)) {
                        StringBuilder sb = new StringBuilder();
                        for (String storeName : storeNameList) {
                            sb.append(storeName).append(",");
                        }
                        // 可用店铺列表文本，逗号分隔，最后一个逗号截取掉
                        String storesTxt = sb.toString().substring(0, sb.toString().length() - 1);
                        detail.setStoresTxt(storesTxt);
                    } else {
                        detail.setStoresTxt("");
                    }
                    redisClient.hset(CacheKeyConstants.INNER_COUPON_DETAIL, coupon.getActivityId(),
                            DJStringUtils.GSON.toJson(detail));
                    redisClient.expire(CacheKeyConstants.INNER_COUPON_DETAIL, CacheKeyConstants.ONE_DAY_EXPIRE_TIME);
                }
            }
        }
        return detail;
    }

    private String getStaffMemberNo(String staffId) {
        StoreManEbuyAccount account = storeManRemoteService.queryStoreManEbuyAccount(staffId);
        if (account != null && StringUtils.isNotBlank(account.getCustNo())) {
            return account.getCustNo();
        }
        String mobile = SCMConfigUtil.getConfig(ConfigConstants.INNER_COUPON_QUERY_MOBILE,
                ConfigConstants.INNER_COUPON_DEFAULT_MOBILE);
        LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
        return memberInfo != null ? memberInfo.getCustNum() : "";
    }

    @Override
    public ReturnMsg<InnerRemain> queryRemainTimes(String staffId) {
        ReturnMsg<InnerRemain> ret = new ReturnMsg<InnerRemain>();
        String dateStr = DateUtils.getDateStrByFormat(new Date(), DATE_FORMAT_YYYYMM);
        String field = dateStr + "_" + staffId;
        String sendTimes = redisClient.hget(CacheKeyConstants.INNER_COUPON_SEND_TIMES_MONTH, field);
        int limit = Integer.parseInt(SCMConfigUtil.getConfig(ConfigConstants.INNER_COUPON_MONTH_LIMIT,
                ConfigConstants.INNER_COUPON_MONTH_LIMIT_DEFAULT));
        int hasSendTimes;
        if (sendTimes == null) {
            hasSendTimes = innerCouponDaoService.querySendTimesByMonth(staffId);
            redisClient.hset(CacheKeyConstants.INNER_COUPON_SEND_TIMES_MONTH, field, String.valueOf(hasSendTimes));
            redisClient.expire(CacheKeyConstants.INNER_COUPON_SEND_TIMES_MONTH, CacheKeyConstants.EXPIRE_TIME_ONE_DAY);
        } else {
            hasSendTimes = Integer.valueOf(sendTimes);
        }
        InnerRemain remain = new InnerRemain();
        remain.setSendTimes(hasSendTimes);
        remain.setRemainTimes(limit - hasSendTimes);
        ret.setData(remain);
        return ret;
    }

    @Override
    public ReturnMsg<CheckRegisterRtn> checkRegister(String mobile, String staffId) {
        ReturnMsg<CheckRegisterRtn> ret = new ReturnMsg<CheckRegisterRtn>();
        CheckRegisterRtn rtn = new CheckRegisterRtn();
        if (!checkStr(mobile, staffId)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
        // 已经是线下会员卡
        if (StringUtils.isNotBlank(memberInfo.getCardNo()) && StringUtils.isBlank(memberInfo.getCustNum())) {
            rtn.setRegisterStatus(LocateMemberRtn.NOT_ONLINE_MEMBER);
        } // 已经是线上会员卡
        else if (StringUtils.isNotBlank(memberInfo.getCustNum()) && StringUtils.isBlank(memberInfo.getCardNo())) {
            rtn.setRegisterStatus(LocateMemberRtn.NOT_OFFLINE_MEMBER);
        } // 已经是融合会员
        else if (StringUtils.isNotBlank(memberInfo.getCardNo()) && StringUtils.isNotBlank(memberInfo.getCustNum())) {
            rtn.setRegisterStatus(LocateMemberRtn.IS_MEMBER);
        } // 既不是线上会员也不是线下会员
        else {
            rtn.setRegisterStatus(LocateMemberRtn.NOT_ONLINEANDOFFLINE_MEMBER);
        }
        if (LocateMemberRtn.NOT_ONLINEANDOFFLINE_MEMBER.equals(rtn.getRegisterStatus())
                || LocateMemberRtn.NOT_ONLINE_MEMBER.equals(rtn.getRegisterStatus())) {
            String model = SCMConfigUtil.getConfig(ConfigConstants.REGISTER_MSG_MODEL,
                    ConfigConstants.REGISTER_MSG_DEFAULT_MODEL);
            String staffName = getStaffNameByStaffId(staffId);
            String memberNo = getStaffMemberNo(staffId);
            String registerUrl = clerkService.getRegisterUrl(memberNo);
            if (StringUtils.isBlank(staffName) || StringUtils.isBlank(registerUrl)) {
                ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E004,
                        PromotionErrorConstants.INNER_COUPON_ERR_MAP);
                return ret;
            }
            String msg = model.replace("{staffName}", staffName).replace("{registerUrl}", registerUrl);
            rtn.setRegisterMsg(msg);
        }
        ret.setData(rtn);
        return ret;
    }

    private String getStaffNameByStaffId(String staffId) {
        String staffName = redisClient.hget(CacheKeyConstants.STAFF_NAME, staffId);
        if (staffName == null) {
            StoreWorkerInfo workInfo = null;
            try {
                workInfo = storeManRemoteService.getWorkInfo(staffId);
            } catch (Exception e) {
                LOGGER.error("getStaffNameByStaffId error,staffId=" + staffId, e);
            }
            staffName = workInfo != null ? workInfo.getWorkerName() : "";
            if (StringUtils.isNotBlank(staffName)) {
                redisClient.hset(CacheKeyConstants.STAFF_NAME, staffId, staffName);
                redisClient.expire(CacheKeyConstants.STAFF_NAME, CacheKeyConstants.ONE_WEEK_EXPIRE_TIME);
            }
        }
        return staffName;
    }

    @Override
    public ReturnMsg<CommonRtn> sendCoupon(String mobile, String activityId, String activityName, String securityKey,
            String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (!checkStr(mobile, staffId, activityId, securityKey)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        // 解密活动编码
        activityId = AESUtils.decrypt(activityId, ConfigConstants.AES_KEY);
        // 判断是否是黑名单
        if (isBlackList(staffId)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E002, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        // 判断当月剩余次数是否大于0
        ReturnMsg<InnerRemain> queryRemainTimes = queryRemainTimes(staffId);
        if (ReturnMsg.SUCCESS.equals(queryRemainTimes.getRetFlag())
                && queryRemainTimes.getData().getRemainTimes() < 1) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E006, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        // 获取会员信息
        LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
        if (memberInfo == null || StringUtils.isBlank(memberInfo.getCustNum())) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E005, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        SendCouponRtn sendCoupon = promotionCouponService.sendCoupon(activityId, "", memberInfo.getCustNum(),
                securityKey, PromSysConstants.BONUS_INNER_PROMOTION, null, null);
        if (sendCoupon != null && PromotionConstants.SUCCESS.equals(sendCoupon.getRetFlag())) {
            InnerCouponDetail couponDetail = new InnerCouponDetail();
            couponDetail.setActivityId(activityId);
            couponDetail.setSecurityKey(securityKey);
            // 获取券规则详情
            couponDetail = createCouponDetail(couponDetail, getStaffMemberNo(staffId),PromSysConstants.BONUS_INNER_PROMOTION);
            InnerCouponRecord record = new InnerCouponRecord();
            record.setCouponRule(couponDetail == null ? "" : couponDetail.getCouponRule());
            record.setStaffId(staffId);
            record.setStaffName(getStaffNameByStaffId(staffId));
            record.setCouponAmount(sendCoupon.getCouponAmount());
            record.setCouponName(sendCoupon.getCouponName());
            record.setActivityId(activityId);
            record.setActivitySecretKey(securityKey);
            record.setSendTime(new Date());
            record.setTelNo(mobile);
            record.setActivityName(activityName);
            record.setCustNo(memberInfo.getCustNum());
            String startTime = sendCoupon.getCouponStartTime();
            String endTime = sendCoupon.getCouponEndTime();
            record.setCouponStartTime(
                    StringUtils.isNotBlank(startTime) && startTime.length() >= 10 ? startTime.substring(0, 10) : "");
            record.setCouponEndTime(
                    StringUtils.isNotBlank(endTime) && endTime.length() >= 10 ? endTime.substring(0, 10) : "");
            innerCouponDaoService.addRecord(record);
            String dateStr = DateUtils.getDateStrByFormat(new Date(), DATE_FORMAT_YYYYMM);
            String field = dateStr + "_" + staffId;
            redisClient.hdel(CacheKeyConstants.INNER_COUPON_SEND_TIMES_MONTH, field);
        } else if (sendCoupon != null && !PromotionConstants.SUCCESS.equals(sendCoupon.getRetFlag())) {
            ret.setError(sendCoupon.getErrorCode(), sendCoupon.getErrorMsg());
        } else {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E007, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
        }
        return ret;
    }
    
    
	public ReturnMsg<CommonRtn> sendCoupon4TM(String custNum, String activityId, String securityKey, String staffId, String trigerId) {
		ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
		if (!checkStr(custNum, staffId, activityId, securityKey)) {
			ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
			return ret;
		}
		// 解密活动编码
		activityId = AESUtils.decrypt(activityId, ConfigConstants.AES_KEY);
		// 判断是否是黑名单
		if (isBlackList(staffId)) {
			ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E002, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
			return ret;
		}
		/** 获取会员信息
		LocateMemberInfo memberInfo = memberInfoService.locateMemberByMobileNo(mobile);
		if (memberInfo == null || StringUtils.isBlank(memberInfo.getCustNum())) {
			ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E005, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
			return ret;
		}**/
		// 查询是否领取过券
		Map<String, Object> couponReceiveMap = timeMachineDao.findReceiveCouponByEmployeeId(staffId);
		if (couponReceiveMap != null && couponReceiveMap.size() > 0) {
			ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E007, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
			return ret;
		}

		SendCouponRtn sendCoupon = promotionCouponService.sendCoupon(activityId, "", custNum, securityKey, trigerId, null, null);
		// 发券成功，记录信息入库
		if (sendCoupon != null && PromotionConstants.SUCCESS.equals(sendCoupon.getRetFlag())) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("employeeId", staffId);
			map.put("customNo", custNum);
			map.put("couponNo", sendCoupon.getCouponNo());
			map.put("activityId", activityId);
			// 领券记录入库
			timeMachineDao.saveReceiveCoupon(map);
			// 更新缓存信息，变成已领券
			String key = TMConstants.TIME_MACHINE_KEY + staffId;
			String data = redisClient.get(key);

			if (StringUtils.isNotEmpty(data)) {
				Gson gson = new Gson();
				TimeMachineVo vo = gson.fromJson(data, TimeMachineVo.class);
				if (vo != null && vo.getUserInfo() != null) {
					vo.getUserInfo().setIsGotCoupon(TMConstants.HAS_GOT_COUPON);
					redisClient.setex(key, TMConstants.EXPIRE_TIME, gson.toJson(vo));
				}
			}

		} else if (sendCoupon != null && !PromotionConstants.SUCCESS.equals(sendCoupon.getRetFlag())) {
			ret.setError(sendCoupon.getErrorCode(), sendCoupon.getErrorMsg());
		} else {
			ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E007, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
		}
		return ret;
	}
    

    @Override
    public ReturnMsg<InnerCouponRecordRtn> queryCouponRecord(String staffId, Integer pageSize, Integer pageNo) {
        pageNo = pageNo != null ? pageNo : 1;
        pageSize = pageSize != null ? pageSize : 10;
        ReturnMsg<InnerCouponRecordRtn> ret = new ReturnMsg<InnerCouponRecordRtn>();
        InnerCouponRecordRtn couponRecord = new InnerCouponRecordRtn();
        int recordCount = innerCouponDaoService.queryRecordCount(staffId);
        List<InCouponRecord> list = new ArrayList<InCouponRecord>();
        if (recordCount > 0) {
            list = innerCouponDaoService.queryRecord(staffId, pageNo, pageSize);
            for (InCouponRecord record : list) {
                record.setMobile(DJStringUtils.desensitiseMobile(record.getMobile()));
                // 判断数据库中用券规则是否为空，为空再掉接口查一次
                if (StringUtils.isBlank(record.getCouponRule())) {
                    InnerCouponDetail detail = queryCouponDetail(staffId, record.getActivityId());
                    if (detail != null && StringUtils.isNotBlank(detail.getCouponRule())) {
                        record.setCouponRule(detail.getCouponRule());
                        // 更新用券规则
                        innerCouponDaoService.updateCouponRuleById(detail.getCouponRule(), record.getId());
                    }
                }
                if (StringUtils.isNotBlank(record.getSendTime()) && record.getSendTime().length() > 20) {
                    record.setSendTime(record.getSendTime().substring(0, record.getSendTime().length() - 2));
                }
                // 页面不需要活动Id
                record.setActivityId(null);
            }
        }
        couponRecord.setRecords(list);
        couponRecord.setSendTotalTimes(recordCount);
        couponRecord.setTotalSize(recordCount);
        ReturnMsg<InnerRemain> queryRemainTimes = queryRemainTimes(staffId);
        if (ReturnMsg.SUCCESS.equals(queryRemainTimes.getRetFlag())) {
            couponRecord.setSendMonthTimes(queryRemainTimes.getData().getSendTimes());
        }
        ret.setData(couponRecord);
        return ret;
    }

    private InnerCouponDetail queryCouponDetail(String staffId, String activityId) {
        if (!checkStr(staffId, activityId)) {
            return null;
        }
        // 查询券记录详情
        List<InnerCouponRecord> couponDetailList = innerCouponDaoService.queryCouponDetailByActivityId(staffId,
                activityId);
        if (CollectionUtils.isEmpty(couponDetailList)) {
            return null;
        }
        InnerCouponRecord record = couponDetailList.get(0);
        InnerCouponDetail couponDetail = new InnerCouponDetail();
        couponDetail.setActivityName(record.getActivityName());
        couponDetail.setActivityId(activityId);
        couponDetail.setSecurityKey(record.getActivitySecretKey());
        // 获取券规则详情
        couponDetail = createCouponDetail(couponDetail, getStaffMemberNo(staffId),PromSysConstants.BONUS_INNER_PROMOTION);
        if (couponDetail == null) {
            return null;
        }
        return couponDetail;
    }

    @Override
    public ReturnMsg<QueryResult<InnerCouponBlackList>> queryBlackList(String staffId, Integer pageNo,
            Integer pageSize) {
        pageNo = pageNo != null ? pageNo : 1;
        pageSize = pageSize != null ? pageSize : 10;
        ReturnMsg<QueryResult<InnerCouponBlackList>> ret = new ReturnMsg<QueryResult<InnerCouponBlackList>>();
        QueryResult<InnerCouponBlackList> qr = new QueryResult<InnerCouponBlackList>();
        List<InnerCouponBlackList> list = new ArrayList<InnerCouponBlackList>();
        int count = innerCouponDaoService.queryBlackListCount(staffId);
        if (count > 0) {
            list = innerCouponDaoService.queryBlackList(staffId, pageSize, pageNo);
            for (InnerCouponBlackList black : list) {
                int sendTimes = innerCouponDaoService.queryRecordCount(black.getStaffId());
                black.setSendTimes(sendTimes);
            }
        }
        
        // 如果redis中没有CacheKeyConstants.INNER_COUPON_BLACK_LIST这个key对应的值，就查数据库补充到redis中去
        // 这步在redis宕机后，缓存的内存数据丢失，手动补数据，做容错使用
        if (!redisClient.exists(CacheKeyConstants.INNER_COUPON_BLACK_LIST)) {
            // 循环取出所有黑名单，加入缓存中，缓存不设置失效时间，一直有效
            int total = innerCouponDaoService.queryBlackListCount(null);
            int totalPageNum = (total / pageSize) + 1;
            List<InnerCouponBlackList> allList = new ArrayList<InnerCouponBlackList>();
            for (int i = 1; i <= totalPageNum; i++) {
                List<InnerCouponBlackList> itemList = innerCouponDaoService.queryBlackList(null, pageSize, i);
                if (CollectionUtils.isNotEmpty(itemList)) {
                    allList.addAll(itemList);
                }
            }
            for (InnerCouponBlackList blackList : allList) {
                redisClient.hset(CacheKeyConstants.INNER_COUPON_BLACK_LIST, blackList.getStaffId(), "");
            }
        }
        
        qr.setTotalSize(count);
        qr.setRecords(list);
        ret.setData(qr);
        return ret;
    }

    @Override
    public ReturnMsg<CommonRtn> addBlack(String staffId, String staffName, String reason) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (!checkStr(staffId, staffName, reason)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        CouponBlackList couponBlackList = new CouponBlackList();
        couponBlackList.setCreateTime(new Date());
        couponBlackList.setReason(reason);
        couponBlackList.setStaffId(staffId);
        couponBlackList.setStaffName(staffName);
        try {
            innerCouponDaoService.addBlack(couponBlackList);
            // 设置黑名单缓存,value值无实际含义，要的是filed值为工号
            redisClient.hset(CacheKeyConstants.INNER_COUPON_BLACK_LIST, staffId, "");
        } catch (DuplicateKeyException e) {
            LOGGER.error("addBlack error,staffId=" + staffId, e);
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E010, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
        }
        
        return ret;
    }

    private boolean checkStr(String... strings) {
        for (String s : strings) {
            if (StringUtils.isBlank(s)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public ReturnMsg<CommonRtn> delBlack(String staffId) {
        ReturnMsg<CommonRtn> ret = new ReturnMsg<CommonRtn>();
        if (!checkStr(staffId)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        innerCouponDaoService.delBlack(staffId);
        // 清除黑名单缓存
        redisClient.hdel(CacheKeyConstants.INNER_COUPON_BLACK_LIST, staffId);
        return ret;
    }

    @Override
    public ReturnMsg<QueryStaffName> queryStaffName(String staffId) {
        ReturnMsg<QueryStaffName> ret = new ReturnMsg<QueryStaffName>();
        if (!checkStr(staffId)) {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E001, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        QueryStaffName queryStaffName = new QueryStaffName();
        // 根据工号查询姓名
        String staffName = getStaffNameByStaffId(staffId);
        if (StringUtils.isNotBlank(staffName)) {
            // 查询工号发券数量
            int count = innerCouponDaoService.queryRecordCount(staffId);
            queryStaffName.setSendTimes(count);
            queryStaffName.setStaffName(staffName);
            ret.setData(queryStaffName);
        } else {
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E011, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
        }
        return ret;
    }

    @Override
    public ReturnMsg<CouponRecordStatisRtn> queryRecord(String staffId, String startTime, String endTime,
            Integer pageSize, Integer pageNo) {
        ReturnMsg<CouponRecordStatisRtn> ret = new ReturnMsg<CouponRecordStatisRtn>();
        pageNo = pageNo != null ? pageNo : 1;
        pageSize = pageSize != null ? pageSize : 10;
        CouponRecordStatisRtn qr = new CouponRecordStatisRtn();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.DEFAULT_DATE_PATTERN);
        // 校验时间格式
        try {
            if (StringUtils.isNotBlank(startTime)) {
                sdf.parse(startTime);
            }
            if (StringUtils.isNotBlank(endTime)) {
                sdf.parse(endTime);
            }
        } catch (ParseException e) {
            LOGGER.error("queryRecord error,staffId=" + staffId, e);
            ret.setError(PromotionErrorConstants.INNER_COUPON_ERR_E009, PromotionErrorConstants.INNER_COUPON_ERR_MAP);
            return ret;
        }
        endTime = endTime + END_TIME_SUFFIXES;
        int count = innerCouponDaoService.queryCouponStatisCount(staffId, startTime, endTime);
        List<CouponRecordStatis> list = new ArrayList<CouponRecordStatis>();
        if (count > 0) {
            list = innerCouponDaoService.queryCouponStatis(staffId, startTime, endTime, pageSize, pageNo);
        }
        int sum = innerCouponDaoService.queryRecordCountByCon(staffId, startTime, endTime);
        qr.setRecords(list);
        qr.setTotalSize(count);
        qr.setRecordCount(sum);
        ret.setData(qr);
        return ret;
    }

    @Override
    public Workbook exportCouponRecord(String staffId, String startTime, String endTime, Integer index) {
        // 导出限制默认两万
        int exptLimit = getExptLimit();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.DEFAULT_DATE_PATTERN);
        // 校验时间格式
        try {
            if (StringUtils.isNotBlank(startTime)) {
                sdf.parse(startTime);
            }
            if (StringUtils.isNotBlank(endTime)) {
                sdf.parse(endTime);
            }
        } catch (ParseException e) {
            LOGGER.error("exportCouponRecord error,staffId=" + staffId, e);
            return null;
        }
        endTime = endTime + END_TIME_SUFFIXES;
        List<InnerCouponRecord> list = innerCouponDaoService.queryRecordByCon(staffId, startTime, endTime, index,
                exptLimit);
        List<String[]> exptList = new ArrayList<String[]>();
        String[] titles = new String[] { "券名称", "工号", "姓名", "发券时间" };
        if (CollectionUtils.isNotEmpty(list)) {
            for (InnerCouponRecord record : list) {
                String[] st = new String[4];
                st[0] = record.getCouponName();
                st[1] = record.getStaffId();
                st[2] = record.getStaffName();
                st[3] = DateUtils.getDateStrByFormat(record.getSendTime(), DateUtils.DEFAULT_TIME_PATTERN);
                exptList.add(st);
            }
        }
        Workbook workbook = ExcelUtils.createExcel(exptList, titles);
        return workbook;
    }

    private int getExptLimit() {
        String limit = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_EXCEL_SIZE,
                ConfigConstants.DEFAULT_MODEL_MANAGE_EXPORT_EXCEL_SIZE);
        return Integer.parseInt(limit);
    }
}
